import { ComponentType } from "./component/index";
import { Sampler, Channel, Animation } from "./component/animation/index";
import { Base } from "./core/Base";
import { any } from "./core/logic";
import { Event } from "./event/index";
class Command extends Base {
    constructor(engine) {
        super();
        this.engine = engine;
        this.alarmids = [];
        this.event = new Event("COMMAND");
    }
    setVisibility(id, flag) {
        let entity = this.engine.scene.get(id);
        if (entity) {
            entity.setVisibility(flag, true);
        }
    }
    /**
     * 炸楼指令
     * @param {*} action 行动：包含"bloom"：炸开，"back":收回
     * @param {*} target 炸开目标,所有可以炸的目标来自于opts.struct,如果"all" 炸开所有，否则炸开单层则为楼层数如：1F，2F，3F
     * @param {*} opts 参考结构
     * {
     *  "id": "",
     *  "type": "zl",
     *  "view": {
     *      "at": [],
    *      "distance": 10,
    *       "pitch": 10,
    *       "roll": 10
    *   },
    *  "floorView":{
    *  },
    *  "dual":1,
    *  "distance":10,
    *  "easing":"none",
    *  "mode":"fly",
    *  "struct": {
    *     "1": {
    *        "floor": "11",
    *        "point": "2"
    *    },
    *    "2": {
    *        "floor": "11",
    *        "point": "2"
    *    },
    *    "3": {
    *        "floor": "11",
    *        "point": "2"
    *    }
    *  }
    * }
     */
    bloomHouse(action, target = "all", opts = {}) {
        const { dual, distance, easing, floorview, view } = opts;
        if (view.roll <= -Math.PI) {
            view.roll = Math.PI * 2 + view.roll;
        }
        const camera = this.engine.scene.getCamera();
        switch (action) {
            case "bloom":
                if (opts.filterPoints) {
                    for (let i = 0; i < opts.filterPoints.length; i++) {
                        let point = this.engine.register.entityManager.get(opts.filterPoints[i]);
                        point.setVisibility(false);
                    }
                }
                if (opts.id && opts.id != "") {
                    // let pop = this.engine.scene.getPopup(opts.label);
                    // if (pop) {
                    //     pop.close();
                    // }
                    let label = this.engine.scene.getEntity(opts.id);
                    if (label) {
                        let board = label.getComponent(ComponentType.Board);
                        if (board) {
                            for (let [key, value] of board.signs) {
                                value.background.visibility = false;
                                value.text.visibility = false;
                            }
                        }
                    }
                }
                if (target == "all") {//全部炸开
                    //相机定位到该位置
                    camera.flyto(view, dual, easing, 0, () => {
                        for (let key in opts.struct) {
                            let f = opts.struct[key].floor;
                            f = this.engine.register.entityManager.get(f);
                            if (!f) {
                                continue;
                            }
                            f.bloom = true;
                            if (!f.trans.default) {
                                f.trans.toString();
                            }
                            f.setVisibility(true);
                            let floor = Number.parseInt(key.substring(0, key.length));
                            f.flyto({ position: [f.trans.default.position[0], f.trans.default.position[1], f.trans.default.position[2] + distance * floor - distance] }, dual, easing);
                            f.alphato(1, dual, easing);
                            if (opts.struct[key].point) {
                                let pids = opts.struct[key].point;
                                for (let i = 0; i < pids.length; i++) {
                                    let point = this.engine.register.entityManager.get(pids[i]);
                                    point.setVisibility(false);
                                }

                            }
                        }
                    });

                } else {//部分炸开
                    let bF = Number.parseInt(target.substring(0, target.length));
                    let total = Object.keys(opts.struct).length;
                    for (let key in opts.struct) {
                        this._bloomPart(key, opts, target);
                    }
                    let v = { at: floorview.at, roll: floorview.roll, pitch: floorview.pitch, distance: floorview.distance + opts.distance * (bF - total) }
                    camera.flyto(v, dual, easing, dual);
                }
                break;
            case "back":
                if (target == "all") {//全部收回
                    for (let key in opts.struct) {
                        this._back(key, opts);
                    }
                    camera.flyto(view, dual, easing, 0, () => {
                        if (opts.id && opts.id != "") {
                            setTimeout(() => {
                                let label = this.engine.scene.getEntity(opts.id);
                                if (label) {
                                    let board = label.getComponent(ComponentType.Board);
                                    if (board) {
                                        for (let [key, value] of board.signs) {
                                            value.background.visibility = true;
                                            value.text.visibility = true;
                                        }
                                    }
                                }
                                if (opts.filterPoints) {
                                    for (let i = 0; i < opts.filterPoints.length; i++) {
                                        let point = this.engine.register.entityManager.get(opts.filterPoints[i]);
                                        point.setVisibility(true);
                                    }
                                }
                            }, dual * 1000);
                        }
                    });
                }
                break;
            default:
                break;
        }
        this.event.commandType = "bloom"; this.event.action = action;
        this.publish(this.event);
    }
    _back(key, opts) {
        const mode = any(opts.vanishType, "fly");
        const dual = any(opts.dual, 0);
        const easing = any(opts.easing, "none");
        let f = opts.struct[key].floor;
        f = this.engine.register.entityManager.get(f);
        if (!f) {
            return;
        }

        if (!f.trans.default) {
            f.trans.toString();
        }
        if (mode == "fly") {
            f.setVisibility(true);
            if (opts.struct[key].point) {
                let pids = opts.struct[key].point;
                for (let i = 0; i < pids.length; i++) {
                    let p = this.engine.register.entityManager.get(pids[i]);
                    p.setVisibility(false);
                }
            }
            f.bloom = false;
            f.flyto({ position: f.trans.default.position }, dual, easing, 0, () => {

            });

        } else if (mode == "fadeout") {
            if (opts.struct[key].point) {
                let pids = opts.struct[key].point;
                for (let i = 0; i < pids.length; i++) {
                    let p = this.engine.register.entityManager.get(pids[i]);
                    p.setVisibility(false);
                }

            }
            f.bloom = false;
            f.flyto({ position: f.trans.default.position }, 0.1, easing, 0, () => {
                f.alphato(1, dual, easing, 0, () => {

                });
            });

        } else {
            throw (new Error("不支持的消失方式"))
        }

    }
    _bloomPart(key, opts, target) {
        const mode = any(opts.vanishType, "fly");
        const dual = any(opts.dual, 0);
        const easing = any(opts.easing, "none");
        let bF = Number.parseInt(target.substring(0, target.length));
        let cF = Number.parseInt(key.substring(0, key.length - 1));
        let f = this.engine.register.entityManager.get(opts.struct[key].floor);
        if (!f) {
            return;
        }
        if (!f.trans.default) {
            f.trans.toString();
        }
        if (mode == "fly") {
            if (cF <= bF) {
                if (opts.struct[key].point) {
                    let pids = opts.struct[key].point;
                    for (let i = 0; i < pids.length; i++) {
                        let point = this.engine.register.entityManager.get(pids[i]);
                        if (cF != bF) {
                            point.setVisibility(false);
                        }

                    }
                }
                f.setVisibility(true);
                f.flyto({ position: f.trans.default.position }, dual, easing, 0, () => {
                    if (opts.struct[key].point) {
                        let pids = opts.struct[key].point;
                        for (let i = 0; i < pids.length; i++) {
                            let point = this.engine.register.entityManager.get(pids[i]);
                            if (cF == bF) {
                                point.setVisibility(true);
                            }
                        }
                    }
                });
            } else {
                if (opts.struct[key].point) {
                    let pids = opts.struct[key].point;
                    for (let i = 0; i < pids.length; i++) {
                        let point = this.engine.register.entityManager.get(pids[i]);
                        if (cF != bF) {
                            point.setVisibility(false);
                        }
                    }
                }
                f.flyto({ position: [opts.view.distance + f.trans.default.position[0], f.trans.default.position[1], f.trans.default.position[2]] }, dual, easing, 0, () => {
                    f.setVisibility(false);
                    if (opts.struct[key].point) {
                        let pids = opts.struct[key].point;
                        for (let i = 0; i < pids.length; i++) {
                            let point = this.engine.register.entityManager.get(pids[i]);
                            if (cF == bF) {
                                point.setVisibility(true);
                            }
                        }
                    }
                });
            }
        } else if (mode == "fadeout") {
            f.flyto({ position: f.trans.default.position }, dual, easing, 0, () => {
                if (cF <= bF) {
                    f.setVisibility(true);
                    if (opts.struct[key].point) {
                        let pids = opts.struct[key].point;
                        for (let i = 0; i < pids.length; i++) {
                            let point = this.engine.register.entityManager.get(pids[i]);
                            if (cF != bF) {
                                point.setVisibility(false);
                            }
                        }
                    }
                    f.alphato(cF <= bF ? 1 : 0, dual, easing, 0, () => {
                        if (opts.struct[key].point) {
                            let pids = opts.struct[key].point;
                            for (let i = 0; i < pids.length; i++) {
                                let point = this.engine.register.entityManager.get(pids[i]);
                                if (cF == bF) {
                                    point.setVisibility(true);
                                }
                            }
                        }
                    });
                } else {
                    if (opts.struct[key].point) {
                        let pids = opts.struct[key].point;
                        for (let i = 0; i < pids.length; i++) {
                            let point = this.engine.register.entityManager.get(pids[i]);
                            if (cF != bF) {
                                point.setVisibility(false);
                            }
                        }
                    }
                    f.alphato(cF <= bF ? 1 : 0, dual, easing, 0, () => {
                        f.setVisibility(false);
                        if (opts.struct[key].point) {
                            let pids = opts.struct[key].point;
                            for (let i = 0; i < pids.length; i++) {
                                let point = this.engine.register.entityManager.get(pids[i]);
                                if (cF == bF) {
                                    point.setVisibility(true);
                                }
                            }
                        }
                    });
                }
            });
        } else {
            throw (new Error("不支持的消失方式"))
        }


    }
    // {
    //     "id": "",
    //     "type": "xj",
    //     "easing": "none",
    //     "stop": true,
    //     "isFirstView":true,
    //     "firstview": {
    //         "at": [],
    //         "distance": 10,
    //         "pitch": 10,
    //         "roll": 10
    //     },
    //     "thirdview": {
    //         "at": [],
    //         "distance": 10,
    //         "pitch": 10,
    //         "roll": 10
    //     },
    //     "inspector": "id",
    //     "inspectorPoints": [
    //         {
    //             "time": 0,
    //             "position": [],
    //             "videoCode": []
    //         },
    //         {
    //             "time": 0,
    //             "position": []
    //         },
    //         {
    //             "time": 0,
    //             "position": [],
    //             "videoCode": []
    //         }
    //     ]
    // }
    trace(action, firstView = true, opts, callback, frameCallback) {
        let easing = any(opts.easing, "none");
        let animation;
        let camera = this.engine.scene.getCamera();
        let inspector = this.engine.register.entityManager.get(opts.inspector);
        if (!inspector) {
            return;
        }
        if (!inspector.trans.default) {
            inspector.trans.toString();
        }
        let kindex = -1;
        switch (action) {
            case "start":
                inspector.setVisibility(!firstView, true);
                inspector.startSkin();
                animation = this.engine.scene.getAnimation(opts.id);
                let view = firstView ? opts.firstview : opts.thirdview;
                if (!animation) {
                    animation = new Animation({
                        id: opts.id, keep: false, loop: 1, autoStart: false, keyFrameCallback: (time) => {
                            if (callback) {
                                let index = -1;
                                for (let i = 0; i < opts.inspectorPoints.length; i++) {
                                    if (time <= (opts.inspectorPoints[i].time + 0.1) * animation.timeScale) {
                                        index = i;
                                        break;
                                    }
                                }
                                if (kindex != index) {
                                    kindex = index;
                                    callback({ time, index, totalTime: animation.dual, opts, command: this });
                                }

                            }
                        }, frameCallback: (info, time) => {
                            if (frameCallback) {
                                frameCallback({ time, totalTime: animation.dual, opts, command: this });
                            }
                        },
                        finalFrameCallback: () => {
                            let start = view;
                            start.at = [opts.inspectorPoints[0].position[0], opts.inspectorPoints[0].position[1], 0];
                            inspector.stopSkin();
                            inspector.setVisibility(false, true);
                            camera.flyto(start, 1, easing, 0, () => {
                                inspector.trans.position = inspector.trans.default.position;
                                inspector.trans.rotation = inspector.trans.default.rotation;
                            });
                        }
                    });
                    let rx = inspector.trans.rotation.x, ry = inspector.trans.rotation.y, rz = inspector.trans.rotation.z;
                    let curRoll, curRotation;
                    let times = [], positions = [], rotation = [], at = [], roll = [];
                    for (let i = 0; i < opts.inspectorPoints.length; i++) {
                        let { time, position } = opts.inspectorPoints[i];

                        if (i == 0) {
                            curRoll = camera.roll;
                            curRotation = [rx, ry, rz];
                        } else {
                            curRoll = roll[roll.length - 1];
                            curRotation = rotation[rotation.length - 1];
                        }
                        times.push(time);
                        positions.push(position);
                        rotation.push(curRotation);
                        at.push([position[0], position[1], 0]);
                        roll.push(curRoll);
                        if (i < opts.inspectorPoints.length - 1) {//非最后一个点
                            times.push(opts.inspectorPoints[i].time + 0.1);
                            positions.push(opts.inspectorPoints[i].position);
                            let prz = Math.atan2(opts.inspectorPoints[i + 1].position[1] - opts.inspectorPoints[i].position[1], opts.inspectorPoints[i + 1].position[0] - opts.inspectorPoints[i].position[0]);
                            prz %= (Math.PI * 2);
                            rotation.push([rx, ry, rz + prz]);
                            at.push([position[0], position[1], 0]);
                            curRoll = Math.atan2(opts.inspectorPoints[i + 1].position[1] - opts.inspectorPoints[i].position[1], opts.inspectorPoints[i + 1].position[0] - opts.inspectorPoints[i].position[0]);
                            curRoll = Math.atan2(opts.inspectorPoints[i + 1].position[1] - opts.inspectorPoints[i].position[1], opts.inspectorPoints[i + 1].position[0] - opts.inspectorPoints[i].position[0]);
                            curRoll = curRoll - Math.PI / 2;
                            curRoll %= (Math.PI * 2);
                            if (curRoll - roll[roll.length - 1] > Math.PI) {
                                curRoll = curRoll - Math.PI * 2;
                            }
                            if (curRoll - roll[roll.length - 1] < -Math.PI) {
                                curRoll = curRoll + Math.PI * 2;
                            }
                            roll.push(curRoll);
                        }
                    }
                    //添加相机动画
                    if (firstView != null || firstView != undefined) {
                        if (firstView) {
                            //人隐藏
                            inspector.setVisibility(false);
                        } else {
                            //人显示添加人动画
                            inspector.setVisibility(true);
                        }
                    }
                    let samplerRotation = new Sampler([...times], rotation, "LINEAR", easing);
                    let channelRotation = new Channel(inspector.trans, "rotation");
                    channelRotation.add(samplerRotation);
                    animation.add(channelRotation);
                    let samplerPosition = new Sampler([...times], positions, "LINEAR", easing);
                    let channelPosition = new Channel(inspector.trans, "position");
                    channelPosition.add(samplerPosition);
                    animation.add(channelPosition);
                    //添加相机动画
                    let samplerAt = new Sampler([...times], at, "LINEAR", easing);
                    let channelAt = new Channel(camera, "at");
                    channelAt.add(samplerAt);
                    animation.add(channelAt);
                    let samplerRoll = new Sampler([...times], roll, "LINEAR", easing);
                    let channelRoll = new Channel(camera, "roll");
                    channelRoll.add(samplerRoll);
                    animation.add(channelRoll);
                    this.engine.scene.addAnimation(animation);
                    let start = view;
                    start.at = [opts.inspectorPoints[0].position[0], opts.inspectorPoints[0].position[1], 0];
                    camera.flyto(start, 1.0, easing, 0, () => {
                        animation.start();
                    });
                } else {
                    //添加相机动画
                    if (firstView != null || firstView != undefined) {
                        if (firstView) {
                            //人隐藏
                            inspector.setVisibility(false);
                        } else {
                            //人显示添加人动画
                            inspector.setVisibility(true);
                        }
                    }
                    animation.start();
                }
                break;
            case "pause":
                inspector.setVisibility(!firstView, true);
                inspector.stopSkin();
                animation = this.engine.scene.getAnimation(opts.id);
                if (animation) {
                    animation.stop();
                }
                break;
            case "stop":
                inspector.setVisibility(false, true);
                inspector.stopSkin();
                animation = this.engine.scene.getAnimation(opts.id);
                if (animation) {
                    animation.stop();
                    this.engine.scene.removeAnimation(opts.id);
                    let start = firstView ? opts.firstview : opts.thirdview;
                    start.at = [opts.inspectorPoints[0].position[0], opts.inspectorPoints[0].position[1], 0];
                    camera.flyto(start, 1, easing, 0, () => {
                        inspector.trans.position = inspector.trans.default.position;
                        inspector.trans.rotation = inspector.trans.default.rotation;
                    });
                }
                break;
            case "changeview":
                if (firstView) {
                    //人隐藏
                    inspector.setVisibility(false);
                    let v = { distance: opts.firstview.distance, pitch: opts.firstview.pitch }
                    camera.flyto(v, 1, easing);
                } else {
                    //人显示添加人动画
                    let v = { distance: opts.thirdview.distance, pitch: opts.thirdview.pitch }
                    camera.flyto(v, 1, easing, 0, () => {
                        inspector.setVisibility(true);
                    })
                }
                break;
            case "speed":
                animation = this.engine.scene.getAnimation(opts.id);
                if (animation) {
                    let speed = any(opts.speed, 1);
                    animation.timeScale = 1 / speed;
                }
                break;
        }
        this.event.commandType = "trace";
        this.event.action = action;
        this.publish(this.event);
        return animation;
    }
    /**
     * 
     * @param {Array} devices 报警的设备[{"type":"",devicecodes:[]}]。
     * @param {*} opts
     * @param {String} opts.color 扩散报警颜色 eg"#ff0000ff"
     * @param {String} opts.radius 扩散最大半径。缺省10。
     * @param {String} opts.thick 扩散圈厚度。缺省1.5。
     * @param {String} opts.easing 扩散动画。缺省"none":线性动画。
     * @param {String} opts.propertyName 告警设备属性名称。
     * @param {Boolean} opts.location 是否定位到最新的报警点。缺省true。
     * @param {Number} opts.dual 定位到报警的时常，单位:秒,缺省1秒。
     */
    alarm(devices, opts = {}) {
        const alarmType = any(opts.alarmType, 0);
        if (alarmType == 1) {
            return this.alarm1(devices, opts);
        }
        const color = any(opts.color, "#ff0000ff");
        const radius = any(opts.radius, 10);
        const thick = any(opts.thick, 1.5);
        const easing = any(opts.easing, "none");
        const location = any(opts.location, true);
        const dual = any(opts.dual, 0.5);
        const radio = any(opts.radio, 1);
        const propertyName = any(opts.propertyName, "devicecode");
        //移除 
        for (let i = 0; i < this.alarmids.length; i++) {
            let id = this.alarmids[i];
            this.engine.scene.removeEntity(id);//移除实体
            this.engine.scene.removeAnimation(id + "#3");//移除动画
            this.engine.scene.removeEntity(id + "#0");//移除告警圆1
            this.engine.scene.removeEntity(id + "#1");//移除告警圆2
            this.engine.scene.removeEntity(id + "#2");//移除告警圆3
            this.engine.scene.removePopup(id + "#4");//移除警告弹窗
        }
        this.alarmids = [];
        for (let i = 0; i < devices.length; i++) {
            let entity = this.engine.scene.getEntity(devices[i].type);
            if (!entity) {
                continue;
            }
            //添加
            const ids = devices[i].devicecodes;
            for (let i = 0; i < ids.length; i++) {
                //添加实体
                const id = ids[i];
                let trans = entity.trans.findInstance(propertyName, id);
                if (!trans) {
                    continue;
                }
                //定位到
                if (location) {
                    this.engine.scene.getCamera().flyto({ at: [trans.position.x, trans.position.y, 0] }, dual);
                }
                let material = new w.material.BasicMaterial({
                    alphaCutoff: 0.0,
                    depthBias: -50,
                    depthBiasSlopeScale: 1,
                    depthBiasClamp: 0,
                    defuseLight: true,
                    blending: "NormalBlending",
                    color: "#ffffff",
                    map: entity.mesh.material.alertMap,
                });
                let size = entity.mesh.geometry.size;
                let geometry = new w.geometry.PointGeometry({ position: [0, 0, 0], size: [size[0] * radio, size[1] * radio], shape: 'rect', verticalLocation: entity.mesh.geometry.verticalLocation });
                let mesh = new w.component.Mesh({ geometry, material })
                let o = new w.Object3D({ id, position: trans.position.toArray() });
                o.addComponent(mesh);
                this.engine.scene.addEntity(o);
                o.linkEntity = entity.id;//关联base实体，确保base能够被拾取到。
                // console.log(o.trans.position);

                //添加弹窗
                if (entity.mesh.material.alarm && entity.mesh.material.alarm.html) {
                    let html = new Function("info", "instanceIndex", `return '${entity.mesh.material.alarm.html}'`)(
                        entity,
                        trans.idx,
                    );
                    let anchor = trans.position.toArray();
                    let pop = new w.info.Popup({
                        id: id + "#4",
                        anchor,
                        content: html
                    });
                    this.engine.scene.addPopup(pop);
                }

                //添加扩散圆
                let m1 = new w.material.DiffuseMaterial({
                    color: "#ffffff",
                    // map: '../pub/assets/earth.jpg',
                    blending: "NormalBlending",
                    colors: ["#00000000", "#00000000", color],
                    radius: [0, 0, 0],
                    depthBias: -50,
                    depthBiasSlopeScale: 1,
                    depthBiasClamp: 0,
                    depthWriteEnabled: false,
                    linear: false,//各个扩散层是否线性混合
                    dOffset: [0, 0, 0]  //扩散中心偏移
                });//标准材质
                let m2 = new w.material.DiffuseMaterial({
                    color: "#ffffff",
                    // map: '../pub/assets/earth.jpg',
                    blending: "NormalBlending",
                    depthWriteEnabled: false,
                    depthBias: -50,
                    depthBiasSlopeScale: 1,
                    depthBiasClamp: 0,
                    colors: ["#00000000", "#00000000", color],
                    radius: [0, 0, 0],
                    linear: false,//各个扩散层是否线性混合
                    dOffset: [0, 0, 0]  //扩散中心偏移
                });//标准材质
                let m3 = new w.material.DiffuseMaterial({
                    color: "#ffffff",
                    // map: '../pub/assets/earth.jpg',
                    blending: "NormalBlending",
                    colors: ["#00000000", "#00000000", color],
                    radius: [0, 0, 0],
                    depthBias: -50,
                    depthBiasSlopeScale: 1,
                    depthBiasClamp: 0,
                    depthWriteEnabled: false,
                    linear: false,//各个扩散层是否线性混合
                    dOffset: [0, 0, 0]  //扩散中心偏移
                });//标准材质
                let kg = new w.geometry.CircleGeometry(
                    {
                        radius, //圆半径
                        section: 36,//段数，值越大越圆
                        back: false //是否再后台线程进行处理
                    })
                let mesh1 = new w.component.Mesh({ geometry: kg, material: m1 });
                let mesh2 = new w.component.Mesh({ geometry: kg, material: m2 })
                let mesh3 = new w.component.Mesh({ geometry: kg, material: m3 })
                let o1 = new w.Object3D({ id: id + "#0", position: trans.position.toArray() });
                let o2 = new w.Object3D({ id: id + "#1", position: trans.position.toArray() });
                let o3 = new w.Object3D({ id: id + "#2", position: trans.position.toArray() });
                o1.addComponent(mesh1);
                o2.addComponent(mesh2);
                o3.addComponent(mesh3);
                this.engine.scene.addEntity(o1);
                this.engine.scene.addEntity(o2);
                this.engine.scene.addEntity(o3);
                //添加动画
                let animation = new w.animation.Animation({ id: id + "#3", loop: 0 });
                //offset
                let s1a = new w.animation.Sampler([0, 1.0, 2.0], [[0.0, 0.0, 0.0], [0, radius - thick, radius], [0.0, 0.0, 0.0]], "LINEAR", easing);
                let c1a = new w.animation.Channel(m1, "radius");
                c1a.add(s1a);
                animation.add(c1a);
                let s1b = new w.animation.Sampler([0, 1.0, 1.99, 2.0], [1, 0, 0, 1], "LINEAR", easing);
                let c1b = new w.animation.Channel(m1, "opacity");
                c1b.add(s1b);
                animation.add(c1b);
                //offset
                let s2a = new w.animation.Sampler([0.5, 1.5, 2.0], [[0.0, 0.0, 0.0], [0, radius - thick, radius], [0.0, 0.0, 0.0]], "LINEAR", easing);
                let c2a = new w.animation.Channel(m2, "radius");
                c2a.add(s2a);
                animation.add(c2a);
                let s2b = new w.animation.Sampler([0.5, 1.5, 1.99, 2.0], [1, 0, 0, 1], "LINEAR", easing);
                let c2b = new w.animation.Channel(m2, "opacity");
                c2b.add(s2b);
                animation.add(c2b);
                //offset
                let s3a = new w.animation.Sampler([1.0, 1.99, 2.0], [[0.0, 0.0, 0.0], [0, radius - thick, radius], [0.0, 0.0, 0.0]], "LINEAR", easing);
                let c3a = new w.animation.Channel(m3, "radius");
                c3a.add(s3a);
                animation.add(c3a);
                let s3b = new w.animation.Sampler([1.0, 1.99, 2.0], [1, 0, 1], "LINEAR", easing);
                let c3b = new w.animation.Channel(m3, "opacity");
                c3b.add(s3b);
                animation.add(c3b);
                this.engine.scene.addAnimation(animation);
                this.alarmids.push(id);//添加告警设备
            }
        }

    }
    /**
     * @param {Array} devices 报警的设备[{"type":"",devicecodes:[]}]。
     * @param {*} opts
     * @param {String} opts.easing 扩散动画。缺省"none":线性动画。
     * @param {String} opts.propertyName 告警设备属性名称。
     * @param {Boolean} opts.location 是否定位到最新的报警点。缺省true。
     * @param {Number} opts.dual 定位到报警的时常，单位:秒,缺省1秒。
     */
    alarm1(devices, opts = {}) {
        const color = any(opts.color, "#ff0000ff");
        const easing = any(opts.easing, "none");
        const location = any(opts.location, true);
        const dual = any(opts.dual, 0.5);
        const propertyName = any(opts.propertyName, "devicecode");
        const radio = any(opts.radio, 1);
        //移除 
        for (let i = 0; i < this.alarmids.length; i++) {
            let id = this.alarmids[i];
            this.engine.scene.removeEntity(id);//移除实体
            this.engine.scene.removeAnimation(id + "#3");//移除动画
        }
        this.alarmids = [];
        for (let i = 0; i < devices.length; i++) {
            let entity = this.engine.scene.getEntity(devices[i].type);
            if (!entity) {
                continue;
            }
            //添加
            const ids = devices[i].devicecodes;
            for (let i = 0; i < ids.length; i++) {
                //添加实体
                const id = ids[i];
                let trans = entity.trans.findInstance(propertyName, id);
                if (!trans) {
                    continue;
                }
                //定位到
                if (location) {
                    this.engine.scene.getCamera().flyto({ at: trans.position.toArray() }, dual);
                }
                let material = new w.material.BasicMaterial({
                    alphaCutoff: 0.0,
                    depthBias: -50,
                    depthBiasSlopeScale: 1,
                    depthBiasClamp: 0,
                    defuseLight: true,
                    blending: "NormalBlending",
                    color,
                    map: entity.mesh.material.alertMap,
                });
                let position = new Float32Array([
                    0, 0, 0,
                ])
                let size = entity.mesh.geometry.size;
                let geometry = new w.geometry.PointGeometry({ position: [0, 0, 0], size: [size[0] * radio, size[1] * radio], shape: 'rect', verticalLocation: entity.mesh.geometry.verticalLocation });
                let mesh = new w.component.Mesh({ geometry, material })
                let o = new w.Object3D({ id, position: trans.position.toArray() });
                o.addComponent(mesh);
                this.engine.scene.addEntity(o);
                //添加动画
                let animation = new w.animation.Animation({ id: id + "#3", loop: 0 });
                let sampler = new w.animation.Sampler([0, 0.3, 0.6], [1, 0.1, 1], "LINEAR", easing);
                let channel = new w.animation.Channel(material, "opacity");
                channel.add(sampler);
                animation.add(channel);
                this.engine.scene.addAnimation(animation);
                this.alarmids.push(id);//添加告警设备
            }
        }

    }
    /**
     * 
     * @param {*} devices [{markerid:"",modelid:"",status:"-1"}] "-1":不在线(灰色),"0":正常（绿色）,"1":告警(红色)
     * @returns 
     */
    alarm_device(devices, opts = {}) {
        const color = any(opts.color, "#ff0000ff");
        const radius = any(opts.radius, 10);
        const thick = any(opts.thick, 1.5);
        const easing = any(opts.easing, "none");
        for (let i = 0; i < devices.length; i++) {
            let device = devices[i];
            const markerid = device.markerid;
            const modelid = device.modelid + "_0_0_0";
            const model1id = device.modelid + "_1_1_0";
            this.engine.scene.removeEntity(markerid + "#0");//移除实体
            this.engine.scene.removeEntity(markerid + "#1");//移除告警圆2
            this.engine.scene.removeEntity(markerid + "#2");//移除告警圆3
            this.engine.scene.removeEntity(markerid + "#3");
            this.engine.scene.removeAnimation(markerid + "#4");//移除动画
            let entity = this.engine.scene.getEntity(markerid);
            if (device.status == "-1") {
                //颜色变为绿色
                let material = new w.material.BasicMaterial({
                    alphaCutoff: 0.0,
                    depthBias: -50,
                    depthBiasSlopeScale: 1,
                    depthBiasClamp: 0,
                    defuseLight: true,
                    blending: "NormalBlending",
                    color: "#ffffff",
                    map: entity.mesh.material.alertMap[0],
                });
                let size = entity.mesh.geometry.size;
                let geometry = new w.geometry.PointGeometry({ position: [0, 0, 0], size, shape: 'rect', verticalLocation: entity.mesh.geometry.verticalLocation });
                let mesh = new w.component.Mesh({ geometry, material })
                let o = new w.Object3D({ id: markerid + "#0", position: entity.trans.position.toArray() });
                o.addComponent(mesh);
                this.engine.scene.addEntity(o);
                o.linkEntity = markerid;//关联base实体，确保base能够被拾取到
                //修改线框颜色
                let model = this.engine.scene.getEntity(modelid);
                if (model) {
                    model.mesh.material.color = "#666666";
                }
                //修改覆盖颜色
                let model1 = this.engine.scene.getEntity(model1id);
                if (model1) {
                    model1.mesh.material.color = "#66666644";
                }
            } else if (device.status == "0") {
                //颜色变为绿色
                let model = this.engine.scene.getEntity(modelid);
                if (model) {
                    model.mesh.material.color = "#00ff00";
                }
                //修改覆盖颜色
                let model1 = this.engine.scene.getEntity(model1id);
                if (model1) {
                    model1.mesh.material.color = "#00ff0044";
                }
            } else if (device.status == "1") {
                //颜色变为绿色
                let material = new w.material.BasicMaterial({
                    alphaCutoff: 0.0,
                    depthBias: -50,
                    depthBiasSlopeScale: 1,
                    depthBiasClamp: 0,
                    defuseLight: true,
                    blending: "NormalBlending",
                    color: "#ffffff",
                    map: entity.mesh.material.alertMap[1],
                });
                let size = entity.mesh.geometry.size;
                let geometry = new w.geometry.PointGeometry({ position: [0, 0, 0], size, shape: 'rect', verticalLocation: entity.mesh.geometry.verticalLocation });
                let mesh = new w.component.Mesh({ geometry, material })
                let o = new w.Object3D({ id: markerid + "#0", position: entity.trans.position.toArray() });
                o.addComponent(mesh);
                this.engine.scene.addEntity(o);
                o.linkEntity = markerid;//关联base实体，确保base能够被拾取到
                let model = this.engine.scene.getEntity(modelid);
                if (model) {
                    model.mesh.material.color = "#ff0000";
                }
                //修改覆盖颜色
                let model1 = this.engine.scene.getEntity(model1id);
                if (model1) {
                    model1.mesh.material.color = "#ff000044";
                }

                //添加扩散圆
                let m1 = new w.material.DiffuseMaterial({
                    color: "#ffffff",
                    // map: '../pub/assets/earth.jpg',
                    blending: "NormalBlending",
                    colors: ["#00000000", "#00000000", color],
                    radius: [0, 0, 0],
                    depthBias: -50,
                    depthBiasSlopeScale: 1,
                    depthBiasClamp: 0,
                    depthWriteEnabled: false,
                    linear: false,//各个扩散层是否线性混合
                    dOffset: [0, 0, 0]  //扩散中心偏移
                });//标准材质
                let m2 = new w.material.DiffuseMaterial({
                    color: "#ffffff",
                    // map: '../pub/assets/earth.jpg',
                    blending: "NormalBlending",
                    depthWriteEnabled: false,
                    depthBias: -50,
                    depthBiasSlopeScale: 1,
                    depthBiasClamp: 0,
                    colors: ["#00000000", "#00000000", color],
                    radius: [0, 0, 0],
                    linear: false,//各个扩散层是否线性混合
                    dOffset: [0, 0, 0]  //扩散中心偏移
                });//标准材质
                let m3 = new w.material.DiffuseMaterial({
                    color: "#ffffff",
                    // map: '../pub/assets/earth.jpg',
                    blending: "NormalBlending",
                    colors: ["#00000000", "#00000000", color],
                    radius: [0, 0, 0],
                    depthBias: -50,
                    depthBiasSlopeScale: 1,
                    depthBiasClamp: 0,
                    depthWriteEnabled: false,
                    linear: false,//各个扩散层是否线性混合
                    dOffset: [0, 0, 0]  //扩散中心偏移
                });//标准材质
                let kg = new w.geometry.CircleGeometry(
                    {
                        radius, //圆半径
                        section: 36,//段数，值越大越圆
                        back: false //是否再后台线程进行处理
                    })
                let mesh1 = new w.component.Mesh({ geometry: kg, material: m1 });
                let mesh2 = new w.component.Mesh({ geometry: kg, material: m2 })
                let mesh3 = new w.component.Mesh({ geometry: kg, material: m3 })
                let o1 = new w.Object3D({ id: markerid + "#1", position: entity.trans.position.toArray() });
                let o2 = new w.Object3D({ id: markerid + "#2", position: entity.trans.position.toArray() });
                let o3 = new w.Object3D({ id: markerid + "#3", position: entity.trans.position.toArray() });
                o1.addComponent(mesh1);
                o2.addComponent(mesh2);
                o3.addComponent(mesh3);
                this.engine.scene.addEntity(o1);
                this.engine.scene.addEntity(o2);
                this.engine.scene.addEntity(o3);
                //添加动画
                let animation = new w.animation.Animation({ id: markerid + "#4", loop: 0 });
                //offset
                let s1a = new w.animation.Sampler([0, 1.0, 2.0], [[0.0, 0.0, 0.0], [0, radius - thick, radius], [0.0, 0.0, 0.0]], "LINEAR", easing);
                let c1a = new w.animation.Channel(m1, "radius");
                c1a.add(s1a);
                animation.add(c1a);
                let s1b = new w.animation.Sampler([0, 1.0, 1.99, 2.0], [1, 0, 0, 1], "LINEAR", easing);
                let c1b = new w.animation.Channel(m1, "opacity");
                c1b.add(s1b);
                animation.add(c1b);
                //offset
                let s2a = new w.animation.Sampler([0.5, 1.5, 2.0], [[0.0, 0.0, 0.0], [0, radius - thick, radius], [0.0, 0.0, 0.0]], "LINEAR", easing);
                let c2a = new w.animation.Channel(m2, "radius");
                c2a.add(s2a);
                animation.add(c2a);
                let s2b = new w.animation.Sampler([0.5, 1.5, 1.99, 2.0], [1, 0, 0, 1], "LINEAR", easing);
                let c2b = new w.animation.Channel(m2, "opacity");
                c2b.add(s2b);
                animation.add(c2b);
                //offset
                let s3a = new w.animation.Sampler([1.0, 1.99, 2.0], [[0.0, 0.0, 0.0], [0, radius - thick, radius], [0.0, 0.0, 0.0]], "LINEAR", easing);
                let c3a = new w.animation.Channel(m3, "radius");
                c3a.add(s3a);
                animation.add(c3a);
                let s3b = new w.animation.Sampler([1.0, 1.99, 2.0], [1, 0, 1], "LINEAR", easing);
                let c3b = new w.animation.Channel(m3, "opacity");
                c3b.add(s3b);
                animation.add(c3b);
                this.engine.scene.addAnimation(animation);
            } else {

            }
        }

    }
}
export { Command }